﻿//
// Copyright 2024 Exhunter Technology Co.Ltd2.
//

using System.Management;
using X18.Framework.Core.Hash;
using X18.Framework.Core.Utils;

namespace X18.Framework.Core.MachineKey
{
    /// <summary>
    /// Windows特征码获取算法
    /// </summary>
    internal class HwNoWindows : HwNoUnit
    {
        public override char Prefix
        {
            get
            {
                return 'Z';
            }
        }

        private const string wql0 = "SELECT * FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)";
        private const string prop0 = "ProcessorId";
        private const string wql1 = "SELECT * FROM Win32_BaseBoard WHERE (Product IS NOT NULL)";
        private const string prop1 = "Product";
        private const string wql2 = "SELECT * FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)";
        private const string prop2 = "SerialNumber";
        private const string wql3 = "SELECT * FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)";
        private const string prop3 = "SerialNumber";

        public override bool TryGet(out string no)
        {
            no = "";
            // 当前不是Windows系统，直接返回失败
            bool result;
            //
            string mbp, mbs, bbs, cpu;
            bool bp = TryGetByProperty(out mbp, wql1, prop1); // 主板厂家
            bool bs = TryGetByProperty(out mbs, wql2, prop2); // 主板序列号
            bool bc = TryGetByProperty(out bbs, wql3, prop3); // BIOS序列号
            bool bb = TryGetByProperty(out cpu, wql0, prop0); // CPU序列号 
            // 获取硬件Hash值
            ulong hash = 0;
            if (bp && bs && !mbp.IsEmpty() && !mbs.IsEmpty())
            {
                hash = MurmurHash.ComputeHashToInt64(mbp + "_" + mbs);
                result = true;
            }
            else if (bb && !bbs.IsEmpty())
            {
                hash = MurmurHash.ComputeHashToInt64(bbs + "");
                result = true;
            }
            else if (bc && !cpu.IsEmpty())
            {
                hash = MurmurHash.ComputeHashToInt64(cpu + "");
                result = true;
            }
            else
            {
                result = false;
            }
            if (result && hash != 0)
            {
                var bytes = GetHashBytes(hash);
                no = GetCode(bytes);
            }
            //
            return result;
        }

        protected bool TryGetByProperty(out string no, string wql, string prop)
        {
            no = null;
            bool result = false;
            try
            {
                var source = new ManagementObjectSearcher(wql);
                foreach (var propertyData in source.Get())
                {
                    if (propertyData != null)
                    {
                        object data = propertyData[prop];
                        if (data != null)
                        {
                            result = true;
                            no = data.ToString();
                            break;
                        }
                    }
                }
            }
            catch
            {
                result = false;
            }
            if (no.IsEmpty())
            {
                no = "";
            }
            return result;
        }
    }
}
